package com.lifesea.notify.mq.handler;

import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import com.alibaba.rocketmq.common.message.MessageExt;
import com.lifesea.commons.cache.RedisConst;
import com.lifesea.rocketmq.utils.handler.MessageHandler;
import com.lifesea.rocketmq.utils.message.MessageDecoder;
import com.lifesea.rocketmq.utils.message.codec.JsonMessageDecoder;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.JedisCluster;

import java.text.ParseException;
import java.util.Date;
import java.util.Map;

/**
 * 挂号科室排班统计处理器
 */
@Component
public class HasSchStatisticsNotifyHandler implements MessageHandler<String> {

    @Autowired
    private JedisCluster jedisCluster;

    private static final Logger logger = LoggerFactory.getLogger(HasSchStatisticsNotifyHandler.class);

    @Override
    public ConsumeConcurrentlyStatus process(String data, MessageExt message, ConsumeConcurrentlyContext context) {
        logger.info("[统计排班]接收,msgId={},notify={}", message.getMsgId(), data);
        String[] nodeArr = StringUtils.splitByWholeSeparatorPreserveAllTokens(data, "@*");

        try {
            String hosId = nodeArr[0];
            String deptId = nodeArr[1];
            String docId = nodeArr[2];

            if (StringUtils.isNotEmpty(deptId)) {// 科室排班
                if (StringUtils.isEmpty(nodeArr[3])) { // 没有排班数据
                    refHosDeptSchStatus(hosId, deptId, false);
                    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                }
                String[] schArr = StringUtils.splitByWholeSeparatorPreserveAllTokens(nodeArr[3], "@$");
                for (String sch : schArr) {
                    String[] temps = StringUtils.splitByWholeSeparatorPreserveAllTokens(sch, "@#");
                    String schId = temps[3];
                    String schDocId = temps[2];
                    int hasRes = Integer.parseInt(temps[4]);
                    String schDate = temps[5];
                    boolean hasSch = hasDeptSch(deptId, schId, hasRes, schDate);
                    // 刷新医院的科室列表状态
                    refHosDeptSchStatus(hosId, String.valueOf(deptId), hasSch);

                    hasSch = hasDocSch(schDocId, schId, hasRes, schDate);

                    refHosDocSchStatus(hosId, schDocId, hasSch);
                }
            } else { // 医生排班

            }
        } catch (Exception e) {
            logger.error("统计排班出错", e);
        }

        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }


    private boolean hasDeptSch(String deptId, String schId, int hasRes, String schDate) {
        String deptSchListKey = getDeptSchListKey(deptId);
        String deptHasSchKey = getDeptHasSchKey(deptId);
        String schIdWithDate = schId + "|" + schDate;
        if (hasRes > 0) {
            jedisCluster.set(deptHasSchKey, "1"); // 设置科室有排班标志
            jedisCluster.hset(deptSchListKey, schIdWithDate, String.valueOf(hasRes));

            return true;
        }

        Map<String, String> deptMap = jedisCluster.hgetAll(deptSchListKey);
        return doSch(deptMap, deptSchListKey, deptHasSchKey, schIdWithDate, hasRes);
    }

    private boolean hasDocSch(String docId, String schId, int hasRes, String schDate) {
        String docSchListKey = getDocSchListKey(docId);
        String docHasSchKey = getDocHasSchKey(docId);
        String schIdWithDate = schId + "|" + schDate;
        if (hasRes > 0) {
            jedisCluster.set(docHasSchKey, "1"); // 设置医生有排班标志
            jedisCluster.hset(docSchListKey, schIdWithDate, String.valueOf(hasRes));
            return true;
        }
        Map<String, String> docMap = jedisCluster.hgetAll(docSchListKey);
        return doSch(docMap, docSchListKey, docHasSchKey, schIdWithDate, hasRes);
    }

    private void refHosDeptSchStatus(String hosId, String deptId, boolean hasRes) {
        String key = getHosDeptSchStatusKey(hosId);

        long result = jedisCluster.hset(key, deptId, hasRes ? "1" : "0");
     }

    private void refHosDocSchStatus(String hosId, String docId, boolean hasRes) {
        String key = getHosDocSchStatusKey(hosId);

        long result = jedisCluster.hset(key, docId, hasRes ? "1" : "0");
     }

    private String getHosDocSchStatusKey(String hosId) {
        return String.format(RedisConst.BOOK_HOS_DOC_SCH_STATUS, hosId);
    }

    private String getHosDeptSchStatusKey(String hosId) {
        return String.format(RedisConst.BOOK_HOS_DEPT_SCH_STATUS, hosId);
    }

    private String getDeptSchListKey(String deptId) {
        return String.format(RedisConst.BOOK_DEPT_SCH_STATISTICS, deptId);
    }

    private String getDeptHasSchKey(String deptId) {
        return String.format(RedisConst.BOOK_DEPT_HAS_SCH, deptId);
    }

    private String getDocSchListKey(String docId) {
        return String.format(RedisConst.BOOK_DOC_SCH_STATISTICS, docId);
    }

    private String getDocHasSchKey(String docId) {
        return String.format(RedisConst.BOOK_DOCHAS_SCH, docId);
    }

    private Date getCurDate() {
        Date curDate = null;
        try {
            return DateUtils.parseDate(DateFormatUtils.format(new Date(), "yyyyMMdd"), "yyyyMMdd");
        } catch (ParseException e) {
            // 忽略
        }
        return null;
    }

    private boolean doSch(Map<String, String> schMap, String schListKey, String hasSchKey, String field, int hasRes) {
        Date curDate = getCurDate();
        for (Map.Entry entry : schMap.entrySet()) {
            if (doExpireSch(schListKey, entry.getKey().toString(), hasRes, curDate)) {
                if (Short.parseShort(String.valueOf(entry.getValue())) > 0) {
                    jedisCluster.set(hasSchKey, "1"); // 设置医生有排班标志
                    jedisCluster.hset(schListKey, field, String.valueOf(hasRes));
                    return true;
                }
            }
        }
        jedisCluster.set(hasSchKey, "0"); // 设置医生没有排班标志
        return false;
    }

    /**
     * 判断排班是否过期
     *
     * @param key
     * @param field
     * @param hasRes
     * @return
     */
    private boolean doExpireSch(String key, String field, int hasRes, Date curDate) {
        String cacheSchDate = StringUtils.substringAfter(field, "|");
        if (StringUtils.isEmpty(cacheSchDate)) {
            jedisCluster.hdel(key, field, String.valueOf(hasRes));

            return true;
        }
        // 判断排班是否过期
        try {
            if (DateUtils.parseDate(cacheSchDate, "yyyy-MM-dd").before(curDate)) {// 排班过期删除
                jedisCluster.hdel(key, field, String.valueOf(hasRes));
                return true;
            }
        } catch (ParseException e) {
            logger.error("日期格式错误,cacheSchDate={}", cacheSchDate);
        }
        return false;
    }

    @Override
    public MessageDecoder<String> getMessageDecoder() {
        return new JsonMessageDecoder<String>(String.class);
    }
}
